package com.itbaizhan.shopping_user_service.util;

import lombok.SneakyThrows;
import org.jose4j.json.JsonUtil;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {
	
	// 公钥
	public final static String PUBLIC_JSON = "{\"kty\":\"RSA\",\"n\":\"2GXIII0tIRDtbFUkTs8EoT-ehyeCsMY3AqRsEwWKbLNCBauVN2pw4ngKCEpDz5jcDr-5WkIrRHFBDByRgjs9D21aX4Rh0bRpQkHCAgycRczrmcfJAWlkSFXkfRU5IFBMJ0RA1GjD-jvvv8NzmF5eTPJhaPPPf5jppD9YFL9O_1VSsEhpwi0hLg27-PdDZJoa3Z1QKgOhqqbTadDRmmWPIt_elmML1W2ffBdOgcDvj1eH9608wzSFwwV8vNJSaqv2mGoLjY77hysS-rWKB27HoIb8Qml_bd-0MmU5IjDfXWhOhzLm-nvsuieZURfWcpjCrGgk97zUrOTAFLinAGm7nQ\",\"e\":\"AQAB\"}";
	
	// 私钥
	public final static String PRIVATE_JSON = "{\"kty\":\"RSA\",\"n\":\"2GXIII0tIRDtbFUkTs8EoT-ehyeCsMY3AqRsEwWKbLNCBauVN2pw4ngKCEpDz5jcDr-5WkIrRHFBDByRgjs9D21aX4Rh0bRpQkHCAgycRczrmcfJAWlkSFXkfRU5IFBMJ0RA1GjD-jvvv8NzmF5eTPJhaPPPf5jppD9YFL9O_1VSsEhpwi0hLg27-PdDZJoa3Z1QKgOhqqbTadDRmmWPIt_elmML1W2ffBdOgcDvj1eH9608wzSFwwV8vNJSaqv2mGoLjY77hysS-rWKB27HoIb8Qml_bd-0MmU5IjDfXWhOhzLm-nvsuieZURfWcpjCrGgk97zUrOTAFLinAGm7nQ\",\"e\":\"AQAB\",\"d\":\"K1AYAffv7_3g372c8k86WIIQ23F7laFe8l7xqM8DmWU50kO5LqnV5WZsb6NZtkwcw7D5SwkSevUGNYPkVgJAYv2ayKKJJ72qEdJyoBFhGBF_mLylzWwIX_gdLzIXyJF55KQjK8C6dTQY9TOMSBOfYVxkResC_cGgBjmNij2OdMmDb-w0tmAZTvJjG3UmXRRhi9PgCnCAIH6jUuMatxkSqZFqWMZCsgD8z0yxip-JMa6tOC9qt307CEPD9Fvfu9GBx6S8jfHInRWnoYldOel7U03dYj4pUSDbmLoCZfKfDFoC3tusbhMHkDnGx1_GP9YecfojlNcBoDVeKlCvUENdmw\",\"p\":\"8ORkv-jPcA4eDL-ZyBEYNS2pYbv96mtYAUraRSgHaHNFy5b3Oo4cZrkVrZg-8ovZBSYhQF03iDm5bE_xFjGjuvNnAr33b-vMgUbjO7ZgS7n0WBvxhY38Abu9YJkou6q8EUP784xiSt7XT0QUtVNrVB0QcGk_HZD2v07zZ8qSEAc\",\"q\":\"5fgejNPMQXarwh5XIf9Um6tMwre-Lc57MZohIV5lulwwdytR8yIvRwWzseKCglKVvyKaf3gXHKyOe3e5aUWCBSc4wgNt7TBlvy43NTQ6PmkDcwRQnv45OKI-DDHalGIjpKGSv4XNkPhvO0252D9Ioa4UGd03cGsTnNZ1o5TpJjs\",\"dp\":\"wqfsed9I8MWXprmVLMQTibVSMDXXIvyG6tRvuH52LgMoHTHqqZh4ftGFIPfrtdcoES8Uo4wv-ZabrViT-lk2czWIwgB72Cb05GpB6Nigy9CCEEjUTBXF1Ci_CTX6Ylu_CTykddO1Acc8uULMcRHtotSxmgSSCfRAT6seqXpZuTU\",\"dq\":\"a82udJHs1FtPFQaoDfXlsbvRlg4QhuSed5grI7tesMf6qEKUfgduZjrUC_WE_Ja-QAV2q36eRwDVIifzsNe2pbfHMZvt8hyX9dEybCx5iTwtM8O4D3BZXqUftRPBxYFj-A8N_d45iVYMvp4nGqo_4Br8rUs4a-imHwWhy_dIfHU\",\"qi\":\"rMydgDt6WKrgiaiWJYX8KPL3nPuGI5MI5VlDFMiPjJVUtJJKMfBaOsGa4YepPwivNbDh5fkjUV8qMpu8zJdliE5iiXyQzHRzJxwqSFwBFw2VZiPUhqKndn4xSiAraiVHHwzBKT8xGHgtgAJh0WiwjkWR4K5W1YsEAEbfxVelNoM\"}";
	
	
	/**
	 * 生成token
	 *
	 * @param userId    用户id
	 * @param username 用户名字
	 * @return
	 */
	@SneakyThrows
	public static String sign(Long userId, String username) {
		// 1、 创建jwtclaims  jwt内容载荷部分
		JwtClaims claims = new JwtClaims();
		// 是谁创建了令牌并且签署了它
		claims.setIssuer("itbaizhan");
		// 令牌将被发送给谁
		claims.setAudience("audience");
		// 失效时间长 （分钟）
		claims.setExpirationTimeMinutesInTheFuture(60 * 24);
		// 令牌唯一标识符
		claims.setGeneratedJwtId();
		// 当令牌被发布或者创建现在
		claims.setIssuedAtToNow();
		// 再次之前令牌无效
		claims.setNotBeforeMinutesInThePast(2);
		// 主题
		claims.setSubject("shopping");
		// 可以添加关于这个主题得声明属性
		claims.setClaim("userId", userId);
		claims.setClaim("username", username);
		
		
		// 2、签名
		JsonWebSignature jws = new JsonWebSignature();
		//赋值载荷
		jws.setPayload(claims.toJson());
		
		
		// 3、jwt使用私钥签署
		PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(PRIVATE_JSON)).getPrivateKey();
		jws.setKey(privateKey);
		
		
		// 4、设置关键 kid
		jws.setKeyIdHeaderValue("keyId");
		
		
		// 5、设置签名算法
		jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
		// 6、生成jwt
		/*
		 * 签署JWS并生成紧凑的序列化或完整的jw/JWS 表示，它是由三个点（'.'）分隔的字符串
		 * 在表单头.payload.签名中使用base64url编码的部件 如果你想对它进行加密，你可以简单地将这个jwt设置为有效负载
		 * 在JsonWebEncryption对象中，并将cty（内容类型）头设置为“jwt”。
		 */
		String jwt = jws.getCompactSerialization();
		return jwt;
	}
	
	
	
	
	/**
	 * 解密token，获取token中的信息
	 *
	 * @param token
	 */
	@SneakyThrows
	public static Map<String, Object> verify(String token){
		// 1、引入公钥
		PublicKey publicKey = new RsaJsonWebKey(JsonUtil.parseJson(PUBLIC_JSON)).getPublicKey();
		// 2、使用jwtcoonsumer  验证和处理jwt
		JwtConsumer jwtConsumer = new JwtConsumerBuilder()
				.setRequireExpirationTime() //过期时间
				.setAllowedClockSkewInSeconds(30) //允许在验证得时候留有一些余地 计算时钟偏差  秒
				.setRequireSubject() // 主题生命
				.setExpectedIssuer("itbaizhan") // jwt需要知道谁发布得 用来验证发布人
				.setExpectedAudience("audience") //jwt目的是谁 用来验证观众
				.setVerificationKey(publicKey) // 用公钥验证签名  验证密钥
				.setJwsAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, AlgorithmIdentifiers.RSA_USING_SHA256))
				.build();
		// 3、验证jwt 并将其处理为 claims
		try {
			JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
			return jwtClaims.getClaimsMap();
		}catch (Exception e){
			return new HashMap();
		}
	}
	
	
	
	
	public static void main(String[] args){
		// 生成
		String baizhan = sign(1001L, "baizhan");
		System.out.println(baizhan);
		
		
		Map<String, Object> stringObjectMap = verify(baizhan);
		System.out.println(stringObjectMap.get("userId"));
		System.out.println(stringObjectMap.get("username"));
	}
}

